1 package eu.simuline.relana.expressions;
2
3 import eu.simuline.relana.model.Deficiency;
4 import eu.simuline.relana.model.DeficiencyMap;
5
6 import java.util.List;
7 import java.util.ArrayList;
8 import java.util.Map;
9 import java.util.HashMap;
10 import java.util.Set;
11 import java.util.HashSet;
12 import java.util.Iterator;
13
14
15
16
17
18
19
20
21
22
23
24 public abstract class Operation {
25
26
27
28
29
30 public enum BaseOps {
31
32
33
34
35
36 Intersection(new IntsOp()) {
37 public String toString() {
38 return "&";
39 }
40 },
41 Union(new UnionOp()) {
42 public String toString() {
43 return "|";
44 }
45 },
46 Complement(new CompOp()) {
47 public String toString() {
48 return "~";
49 }
50 };
51
52
53
54
55
56 BaseOps(Operation oper) {
57 this.oper = oper;
58 }
59
60
61
62
63
64 private static final Map<String, BaseOps> KEY2OP;
65
66 static {
67 KEY2OP = new HashMap<String, BaseOps>();
68 KEY2OP.put(Intersection.toString(), Intersection);
69 KEY2OP.put(Union .toString(), Union );
70 KEY2OP.put(Complement .toString(), Complement );
71 }
72
73
74
75
76
77 private Operation oper;
78
79
80
81
82
83 Operation getOperation() {
84 return this.oper;
85 }
86
87 public static Operation getOperation(String str) {
88 BaseOps oper = KEY2OP.get(str);
89 if (oper == null) {
90 throw new IllegalStateException
91 ("Unknown operation \"" + str + "\". ");
92 }
93 return oper.getOperation();
94 }
95 }
96
97
98
99
100 static final class IntsOp extends Operation implements Eval {
101
102 IntsOp() {
103
104 }
105
106
107
108
109
110 boolean arity1() {
111 return false;
112 }
113
114 public Type retType(Set<FormulaDecl> args) {
115 Iterator<FormulaDecl> iter = args.iterator();
116 if (!iter.hasNext()) {
117 throw new IllegalArgumentException
118 ("Expected at least one argument. ");
119 }
120 Type proto = iter.next().retType();
121
122 while (iter.hasNext()) {
123 if (!proto.equals(iter.next().retType())) {
124
125 List<Type> argTypes = new ArrayList<Type>();
126 for (FormulaDecl form : args) {
127 argTypes.add(form.retType());
128 }
129 throw new IllegalArgumentException
130 ("Expected all the same types; found " + args +
131 " with types " + argTypes + ". ");
132 }
133 }
134 return proto;
135 }
136
137 public Set<Deficiency> eval(Set<Set<Deficiency>> param) {
138 Iterator<Set<Deficiency>> iter = param.iterator();
139 assert iter.hasNext();
140 Set<Deficiency> result = new HashSet<Deficiency>(iter.next());
141 while (iter.hasNext()) {
142 result.retainAll(iter.next());
143 }
144 return result;
145 }
146
147 public Eval getEval(Type type) {
148 return this;
149 }
150
151 public Operation getOperation() {
152 return this;
153 }
154
155 boolean isIsoAntitone() {
156 return true;
157 }
158
159 public String toString() {
160 return "&";
161 }
162 }
163
164
165
166
167 static final class UnionOp extends Operation implements Eval {
168
169 boolean arity1() {
170 return false;
171 }
172
173 public Type retType(Set<FormulaDecl> args) {
174 Iterator<FormulaDecl> iter = args.iterator();
175 if (!iter.hasNext()) {
176 throw new IllegalArgumentException
177 ("Expected at least one argument. ");
178 }
179 Type proto = iter.next().retType();
180
181 while (iter.hasNext()) {
182 if (!proto.equals(iter.next().retType())) {
183
184 List<Type> argTypes = new ArrayList<Type>();
185 for (FormulaDecl form : args) {
186 argTypes.add(form.retType());
187 }
188 throw new IllegalArgumentException
189 ("Expected all the same types; found " + args +
190 " with types " + argTypes + ". ");
191 }
192 }
193 return proto;
194 }
195
196 public Set<Deficiency> eval(Set<Set<Deficiency>> param) {
197 Set<Deficiency> result = new HashSet<Deficiency>();
198 for (Set<Deficiency> set : param) {
199 result.addAll(set);
200 }
201 return result;
202 }
203
204 public Eval getEval(Type type) {
205 return this;
206 }
207
208 public Operation getOperation() {
209 return this;
210 }
211
212 boolean isIsoAntitone() {
213 return true;
214 }
215 public String toString() {
216 return "|";
217 }
218 }
219
220
221
222
223 static final class CompOp extends Operation {
224 boolean arity1() {
225 return true;
226 }
227 public Type retType(Set<FormulaDecl> args) {
228 Iterator<FormulaDecl> iter = args.iterator();
229 if (!iter.hasNext()) {
230 throw new IllegalArgumentException
231 ("Expected at least one argument. ");
232 }
233 Type proto = iter.next().retType();
234 if (iter.hasNext()) {
235 throw new IllegalArgumentException
236 ("Expected no more than one argument. ");
237 }
238 return proto.getInverse();
239
240 }
241
242 public Eval getEval(final Type type) {
243 return new Eval() {
244 public Set<Deficiency> eval(Set<Set<Deficiency>> param) {
245 Set<Deficiency> result = type.asSet();
246 Iterator<Set<Deficiency>> iter = param.iterator();
247 result.removeAll(iter.next());
248 assert !iter.hasNext();
249 return result;
250 }
251 public Operation getOperation() {
252 return CompOp.this;
253 }
254
255 };
256 }
257
258 boolean isIsoAntitone() {
259 return false;
260 }
261 public String toString() {
262 return "~";
263 }
264 }
265
266
267
268
269
270 public enum Functor {
271
272
273
274
275
276 Covariant() {
277 public boolean isAllowed(DeficiencyMap map) {
278 return map.isTwistIsotone();
279 }
280 public String twistIsotone() {
281 return "twist-isotone";
282 }
283 Set<Deficiency> eval(DeficiencyMap map, Set<Deficiency> defs) {
284 return map.cov(defs);
285 }
286 Type source(DeficiencyMap map) {
287 return map.getSource().getType();
288 }
289 Type target(DeficiencyMap map) {
290 return map.getTarget().getType();
291 }
292 String getSymbol() {
293 return ",";
294 }
295 },
296 Contravariant() {
297 public boolean isAllowed(DeficiencyMap map) {
298 return map.isIsotone();
299 }
300 public String twistIsotone() {
301 return "isotone";
302 }
303 Set<Deficiency> eval(DeficiencyMap map, Set<Deficiency> defs) {
304 return map.cont(defs);
305 }
306 Type source(DeficiencyMap map) {
307 return map.getTarget().getType();
308 }
309 Type target(DeficiencyMap map) {
310 return map.getSource().getType();
311 }
312 String getSymbol() {
313 return "'";
314 }
315 };
316
317
318
319
320
321 public abstract boolean isAllowed(DeficiencyMap map);
322 public abstract String twistIsotone();
323 abstract Type source(DeficiencyMap map);
324 abstract Type target(DeficiencyMap map);
325
326 Set<Deficiency> eval(Set<Set<Deficiency>> param,
327 DeficiencyMap map) {
328 assert param.size() == 1;
329 return eval(map, param.iterator().next());
330 }
331 abstract Set<Deficiency> eval(DeficiencyMap map,
332 Set<Deficiency> defs);
333
334 Type retType(Set<FormulaDecl> args, Maps mapOper) {
335 Type retType = args.iterator().next().retType();
336 if (!source(mapOper.getMap()).equals(retType)) {
337 throw new IllegalArgumentException
338 ("Cannot apply \"" + mapOper +
339 "\" to formula \"" + args.iterator().next() +
340 "\" with return type " + retType + ". ");
341 }
342 return target(mapOper.getMap());
343 }
344
345 abstract String getSymbol();
346
347 private static final Map<String, Operation.Functor> ACC2FUNCT;
348
349 static {
350 ACC2FUNCT = new HashMap<String, Operation.Functor>();
351 ACC2FUNCT.put(Operation.Functor.Covariant .getSymbol(),
352 Operation.Functor.Covariant);
353 ACC2FUNCT.put(Operation.Functor.Contravariant.getSymbol(),
354 Operation.Functor.Contravariant);
355 }
356
357 public static Functor covCont(String acc) {
358 return ACC2FUNCT.get(acc);
359 }
360 }
361
362
363
364
365
366 public static final class Maps extends Operation implements Operation.Eval {
367
368
369
370
371
372 private final String funName;
373 private final boolean isInverted;
374 private final DeficiencyMap map;
375 private final Functor funct;
376
377
378
379
380
381 public Maps(String funName,
382 boolean isInverted,
383 DeficiencyMap map,
384 Functor funct) {
385 this.funName = funName;
386 this.isInverted = isInverted;
387 this.map = map;
388 this.funct = funct;
389 if (!funct.isAllowed(map)) {
390 throw new IllegalArgumentException
391 ("Map \"" + this.funName +
392 "\" is not " + funct.twistIsotone() +
393 " and so corresponding functor \"" + this +
394 "\" is not defined. ");
395 }
396 }
397
398
399
400
401
402 private DeficiencyMap getMap() {
403 return this.map;
404 }
405
406 boolean arity1() {
407 return true;
408 }
409 public Type retType(Set<FormulaDecl> args) {
410 return this.funct.retType(args, this);
411 }
412 public Set<Deficiency> eval(Set<Set<Deficiency>> param) {
413 return this.funct.eval(param, this.map);
414 }
415
416 public Operation.Eval getEval(Type type) {
417 return this;
418 }
419
420 public Operation getOperation() {
421 return this;
422 }
423
424
425
426 public boolean isIsoAntitone() {
427 return true;
428 }
429 public String toString() {
430 StringBuffer res = new StringBuffer();
431 res.append(this.funName);
432 if (this.isInverted) {
433 res.append('!');
434 }
435 res.append(this.funct.getSymbol());
436 return res.toString();
437 }
438 }
439
440
441
442
443 public interface Eval {
444
445 Set<Deficiency> eval(Set<Set<Deficiency>> param);
446 Operation getOperation();
447 }
448
449
450
451
452
453 public Operation() {
454
455 }
456
457
458
459
460
461
462
463 abstract boolean arity1();
464
465 abstract boolean isIsoAntitone();
466
467 public abstract Type retType(Set<FormulaDecl> args);
468 public abstract Eval getEval(Type type);
469
470
471
472 public static Operation getOperation(BaseOps baseOps) {
473 return baseOps.getOperation();
474 }
475
476 public static Operation getOperation(String funName,
477 boolean isInverted,
478 DeficiencyMap map,
479 Functor funct) {
480 return new Maps(funName, isInverted, map, funct);
481 }
482
483 }