1 package org.simantics.scl.runtime.unification;
3 import java.util.ArrayList;
5 import org.simantics.scl.runtime.function.Function;
6 import org.simantics.scl.runtime.tuple.Tuple;
7 import org.simantics.scl.runtime.tuple.Tuple0;
9 public class UPending {
10 private static final int STATE_UNFORCED = 0;
11 private static final int STATE_CURRENTLY_FORCING = 1;
12 private static final int STATE_FORCED = 2;
13 private static final int STATE_UNFORCED_CHECK_PENDING = 3;
15 @SuppressWarnings("rawtypes")
16 private final Function proc;
17 private int state = 0;
18 private Object value = null;
20 @SuppressWarnings("rawtypes")
21 public UPending(Function proc) {
25 @SuppressWarnings("unchecked")
26 public Object force() {
29 state = STATE_CURRENTLY_FORCING;
30 value = proc.apply(Tuple0.INSTANCE);
33 case STATE_CURRENTLY_FORCING:
34 throw new RuntimeUnificationException("Pending unification node depends recursively on itself.");
37 case STATE_UNFORCED_CHECK_PENDING: {
38 ArrayList<Object> checks = (ArrayList<Object>)value;
39 state = STATE_CURRENTLY_FORCING;
40 value = proc.apply(Tuple0.INSTANCE);
42 for(Object check : checks)
43 semiUnification(value, check);
47 throw new IllegalStateException();
51 @SuppressWarnings("unchecked")
52 public void checkAgains(Object check) {
53 ArrayList<Object> checks;
56 checks = new ArrayList<Object>(2);
58 state = STATE_UNFORCED_CHECK_PENDING;
61 case STATE_CURRENTLY_FORCING:
62 throw new RuntimeUnificationException("Pending unification node depends recursively on itself.");
64 semiUnification(value, check);
66 case STATE_UNFORCED_CHECK_PENDING:
67 checks = (ArrayList<Object>)value;
71 throw new IllegalStateException();
75 @SuppressWarnings("unchecked")
76 private static void semiUnification(Object constant, Object pendingOrConsOrConstant) {
77 if(pendingOrConsOrConstant instanceof UCons) {
78 UCons cons = (UCons)pendingOrConsOrConstant;
79 Tuple components = (Tuple)cons.tag.destructor.apply(constant);
80 Unification.unify(cons.components, components);
81 cons.components = components;
83 else if(pendingOrConsOrConstant instanceof UPending) {
84 UPending pending = (UPending)pendingOrConsOrConstant;
85 Object otherConstant = pending.force();
86 if(constant == null ? otherConstant != null : !constant.equals(otherConstant))
87 throw new RuntimeUnificationException("Unification failed: " + constant + " != " + otherConstant + ".");
90 if(constant == null ? pendingOrConsOrConstant != null : !constant.equals(pendingOrConsOrConstant))
91 throw new RuntimeUnificationException();