[go: up one dir, main page]

Menu

[r9]: / decker / model / Structure.java  Maximize  Restore  History

Download this file

216 lines (176 with data), 7.5 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
package decker.model;
import java.io.*;
import decker.util.*;
/** if variables_see_each_other is true the variables inside the structure see each other
* that is, when an expression stored in a variable is executed it can reference other variables from the structure */
public final class Structure
{
private final StringTreeMap members = new StringTreeMap();
public Structure (final String type_name) {
this (type_name, false);
}
Structure (final Structure original) {
StringTreeMap.Iterator i = original.members.getIterator();
while (i.hasNext()) {
final StringTreeMap.TreeNode n = i.nextNode();
addDirectly(n.getKey()).setDirectly((Value)n.getValue(), false);
}
}
Structure (final String type_name, final boolean explicitly_expandable) {
addDirectly("structure_type").set(type_name);
// if there exists a template structure for this type, copy it
if (ScriptNode.stack[ScriptNode.RULESET_STACK_SLOT] != null) {
final Value template_value = ScriptNode.stack[ScriptNode.RULESET_STACK_SLOT].get("STRUCTURE_TYPES").get(type_name);
// copy the predefined STRUCTURE_TYPE. instead of copying the optional initializer function of the STRUCTURE_TYPE,
// that function gets executed for this new Structure
if (template_value != null) {
final Structure template = template_value.structure();
StringTreeMap.Iterator i = template.members.getIterator();
Value initializer = null;
while (i.hasNext()) {
final StringTreeMap.TreeNode n = i.nextNode();
if (n.getKey().equals("initializer"))
initializer = (Value) n.getValue();
else
addDirectly(n.getKey()).setDirectly((Value)n.getValue(), false);
}
// execute the STRUCTURE_TYPE's initializer function if there is one
if (initializer != null && initializer.typeDirect() == Value.FUNCTION)
FunctionCall.executeFunctionCall(initializer, null, this);
}
}
if (explicitly_expandable)
add("expandable").set(true);
}
/** creates a special LOCAL structure for a FunctionCall. arguments must be an ARRAY structure containing all the argument values the caller supplied in the function call*/
Structure (final Structure arguments, final String[] argument_names) {
this ("LOCAL");
if (!arguments.get("structure_type").equals("ARRAY"))
throw new RuntimeException("the list of arguments must be a an ARRAY structure");
Structure ret = new Structure("FUNCTION_CALL");
add("argument").set(arguments);
add("return_value");
add("expandable").set(true);
// manually add all the named arguments to the structure - they contain the same variable as the arguments array, not just the same value
final int argument_count = arguments.get("size").integer();
for (int i = argument_names.length; --i >= 0; ) {
if (i >= argument_count)
add(argument_names[i]);
else
members.put(argument_names[i], arguments.get(i+""));
}
}
/** adds a new variable to this collection */
public Value add (String name) {
final Value ret = new Value(this);
if (get("structure_type").equals("ARRAY") &&( name.equals("") || name.equals(((Value)members.get("size")).toString()) )) {
final Value size = (Value) members.get("size");
final int size_int = size.integer();
size.set(size_int+1);
name = size_int+"";
}
final Value overwritten_value = (Value) members.put(name, ret);
if (overwritten_value != null)
overwritten_value.destroy();
return ret;
}
/** adds a vriable to this Structure without doing any tests, like whether the Structure is an ARRAY and the added variable is "" */
public Value addDirectly (String name) {
final Value ret = new Value(this);
members.put(name, ret);
return ret;
}
boolean canHoldCustomVariables () {
final Object o = members.get("expandable");
return o != null && ((Value)o).equals(true);
}
/** removes all members from the structure */
public void clear () { members.clear(); }
public Value deleteFromArray (final int index) {
Value vsize = (Value) members.get("size");
if (get("structure_type").equals("ARRAY") && index >= 0 && index < vsize.integer()) {
final int size = vsize.integer();
final Value ret = (Value) members.get(index+"");
for (int i = index+1; i < size; i++)
members.put((i-1)+"", members.get(i+""));
vsize.set(size-1);
members.remove((size-1)+"");
return ret;
}
return null;
}
/** returns a member variable from this collection but doesn't add it if it doesn't exist yet */
public Value get (final String name) {
return (Value) members.get(name);
}
public Value getValue (final String name) {
final Value ret = (Value) members.get(name);
return (ret == null) ? null : ret.getValue();
}
public Value insertIntoArray (final int index) {
Value vsize = (Value) members.get("size");
if (get("structure_type").equals("ARRAY") && index >= 0 && index <= vsize.integer()) {
final int size = vsize.integer();
for (int i = size; i > index; i--)
members.put(i+"", members.get((i-1)+""));
final Value ret = new Value(this);
members.put(index+"", ret);
vsize.set(size+1);
return ret;
}
return null;
}
public boolean print (final PrintStream out, final String indentation, boolean line_start) {
final String ind = indentation+Global.BLOCK_INDENT;
out.print((line_start?indentation:"") + get("structure_type"));
// make sure we're not going too deep into recurions
if (ind.length() == 10*Global.BLOCK_INDENT.length()) {
if (members.size() > 0)
out.println(ind+"...");
}
else {
// print everything except for ARRAYs
if (!get("structure_type").equals("ARRAY")) {
out.println(); // gotta add a line feed behind the structure type
final StringTreeMap.Iterator i = members.getIterator();
while (i.hasNext()) {
final StringTreeMap.TreeNode n = i.nextNode();
out.print(ind + n.getKey() + " = ");
final Value v = (Value) n.getValue();
if (v.typeDirect() == Value.STRUCTURE)
v.structure().print(out, ind, false);
else if (v.typeDirect() == Value.FUNCTION)
v.function().print(out, ind, false);
else
out.println(v.toString());
}
}
else {
// it's an array. display it
// display the arraysize behind the ARRAY tag
final int count = get("size").integer();
out.println(" ("+count+")");
for (int j = 0; j < count; j++) {
final Value v = get(j+"");
if (v.type() == Value.STRUCTURE)
v.structure().print(out, ind, true);
else if (v.type() == Value.FUNCTION)
v.function().print(out, ind, true);
else
out.println(ind+v.toString());
}
}
}
return true;
}
void putDirectlyIntoStringTreeMap (final String key, final Value v) { members.put(key, v); }
void remove (final String key) {
final Value overwritten_value = (Value) members.remove(key);
if (overwritten_value != null)
overwritten_value.destroy();
}
public int size () { return members.size(); }
public String toString () { return ((Value)members.get("structure_type")).string(); }
boolean staticStackEntry () { final Object o = members.get("static_stack_entry"); return o != null && ((Value)o).equals(true); }
public boolean variablesSeeEachOther () { final Object o = members.get("variables_see_each_other"); return o != null && ((Value)o).equals(true); }
}