1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package jTrolog.terms;
23
24 import jTrolog.parser.Parser;
25 import jTrolog.terms.EvaluableTerm;
26 import jTrolog.engine.Prolog;
27
28 import java.util.*;
29
30
31
32
33
34 @SuppressWarnings({ "rawtypes", "unchecked","serial","unused" })
35 public class Struct extends EvaluableTerm {
36
37 public final String name;
38 public final String predicateIndicator;
39
40 public final int arity;
41 public int operatorType = -1;
42
43 private Term[] args;
44 private Var[] varList;
45
46 public Var[] getVarList() {
47 return varList;
48 }
49
50 Struct(String n, int arity, String predIndic) {
51 type = Term.STRUCT;
52 name = n;
53 this.arity = arity;
54 predicateIndicator = predIndic;
55 }
56
57
58
59
60 public Struct(String f, Term[] argList, int opType) {
61 this(f, argList);
62 operatorType = opType;
63 }
64
65
66
67
68 public Struct(String f, Term[] argList) {
69 this((Parser.removeApices(f)).intern(), argList.length, (Parser.wrapAtom(f) + "/" + argList.length).intern());
70 args = argList;
71 varList = (Var[]) getChildrenVarList(args).toArray(new Var[0]);
72
73 }
74
75
76
77
78
79
80 public Term getArg(int index) {
81 return args[index];
82 }
83
84 public int getOperatorType() {
85 return operatorType;
86 }
87
88 private static List getChildrenVarList(Term[] args) {
89 List findings = new ArrayList();
90 for (int i = 0; i < args.length; i++) {
91 Term arg = args[i];
92 if (arg instanceof Var)
93 findings.add(arg);
94 else if (arg instanceof Struct) {
95 Var[] childsVars = ((Struct) arg).varList;
96 if (childsVars != null && childsVars.length > 0)
97 findings.addAll(Arrays.asList(childsVars));
98 }
99 }
100 return findings;
101 }
102
103
104
105
106
107
108
109 public String toString() {
110 return predicateIndicator == Parser.listSignature ? toStringList(false) : toStringImpl(false);
111 }
112
113 public String toStringList(boolean small) {
114 StringBuffer res = new StringBuffer("[");
115 boolean firstPass = true;
116 int stopPrinting = Integer.MAX_VALUE;
117 for (Iterator it = iterator(this); it.hasNext();) {
118 if (small) {
119 if (stopPrinting-- == 0) {
120 Term last = (Term) it.next();
121 for (; it.hasNext(); last = (Term) it.next())
122 ;
123 if (last.equals(emptyList))
124 return res.append(" ... ").append("]").toString();
125 return res.append(" ... ").append("|").append(last.toStringSmall()).append("]").toString();
126 }
127 }
128 Term child = (Term) it.next();
129 if (!it.hasNext()) {
130 if (child.equals(emptyList))
131 return res.append(']').toString();
132 return res.append('|').append(small ? child.toStringSmall() : child.toString()).append(']').toString();
133 }
134 if (firstPass)
135 firstPass = false;
136 else
137 res.append(", ");
138 res.append(small ? child.toStringSmall() : child.toString());
139 }
140 throw new RuntimeException("bug");
141 }
142
143 public String toStringSmall() {
144 return predicateIndicator == Parser.listSignature ? toStringList(true) : toStringImpl(true);
145 }
146
147 private String toStringImpl(boolean small) {
148
149 if (predicateIndicator == Parser.commaSignature) {
150 String a = small ? getArg(0).toStringSmall() : getArg(0).toString();
151 String b = small ? getArg(1).toStringSmall() : getArg(1).toString();
152 return a + name + " " + b;
153 }
154
155 int opType = getOperatorType();
156 if (opType == Prolog.XFX || opType == Prolog.YFX || opType == Prolog.XFY) {
157 String a = small ? getArg(0).toStringSmall() : getArg(0).toString();
158 String b = small ? getArg(1).toStringSmall() : getArg(1).toString();
159 return a + " " + name + " " + b;
160 }
161 if (opType == Prolog.XF || opType == Prolog.YF) {
162 String a = small ? getArg(0).toStringSmall() : getArg(0).toString();
163 return a + " " + name;
164 }
165 if (opType == Prolog.FX || opType == Prolog.FY) {
166 String a = small ? getArg(0).toStringSmall() : getArg(0).toString();
167 return name + " " + a;
168 }
169
170 if (name.equals("{}")) {
171 if (arity == 0)
172 return name;
173 if (arity == 1)
174 return "{" + (small ? getArg(0).toStringSmall() : getArg(0).toString()) + "}";
175 }
176 StringBuffer res = new StringBuffer(Parser.wrapAtom(name));
177 res.append("(");
178 for (int i = 0; i < arity; i++) {
179 Term arg = getArg(i);
180 if (arg instanceof Struct && ((Struct) arg).predicateIndicator == Parser.commaSignature)
181 res.append("(").append(small ? arg.toStringSmall() : arg.toString()).append(")");
182 else
183 res.append(small ? arg.toStringSmall() : arg.toString());
184 if (i < arity - 1)
185 res.append(", ");
186 }
187 res.append(")");
188 return res.toString();
189 }
190
191 public boolean equals(Object t) {
192 if (!(t instanceof Struct))
193 return false;
194 Struct other = (Struct) t;
195 if (!predicateIndicator.equals(other.predicateIndicator))
196 return false;
197
198 Struct s1 = (Struct) t;
199 if (arity != s1.arity)
200 return false;
201 for (int i = 0; i < s1.arity; i++) {
202 if (!getArg(i).equals(s1.getArg(i)))
203 return false;
204 }
205 return true;
206 }
207
208 public static Iterator iterator(Struct structList) {
209 final Struct origin = (Struct) (structList instanceof Wrapper ? ((Wrapper) structList).getBasis() : structList);
210 Iterator it = new ListIterator(origin);
211 if (structList instanceof Wrapper)
212 return new Wrapper.WrappedIterator(it, ((Wrapper) structList).getContext());
213 return it;
214 }
215
216 private void prepArrays() {
217
218
219 int size = 1;
220 for (int i = 0; i < arity; i++) {
221 Term arg = args[i];
222 if (arg instanceof Struct && ((Struct) arg).arity > 0)
223 size += ((Struct) arg).prePost.length;
224 else
225 size++;
226 }
227 prePost = new int[size];
228 tree = new Term[size];
229
230 int pos = 0;
231
232 prePost[pos] = size - 1;
233 tree[pos] = this;
234 upDateChild(pos++);
235
236 int position = 0;
237 for (int i = 0; i < arity; i++) {
238 Term child = getArg(i);
239 if (child instanceof Struct && ((Struct) child).arity > 0) {
240 Struct cs1 = (Struct) child;
241 Term[] valuesArr = cs1.tree;
242 int[] prePostArr = cs1.prePost;
243 int childSize = valuesArr.length;
244
245 for (int j = 0; j < childSize; j++) {
246 this.prePost[pos] = prePostArr[j] + position;
247 this.tree[pos] = valuesArr[j];
248 upDateChild(pos++);
249 }
250 position += childSize;
251 } else {
252 prePost[pos] = position++;
253 tree[pos] = child;
254 upDateChild(pos++);
255 }
256 }
257 }
258
259 private void upDateChild(int i) {
260 Term child = tree[i];
261 child.tree = tree;
262 child.prePost = prePost;
263 child.pos = i;
264 }
265 }