Skip to content

Commit be6ad5e

Browse files
committed
Support setting individual values in a matrix.
Calling @matrix[@x] now returns a CReal2dMatrixRow, which supports the set operation, passing it through into the parent object. This also creates the ArrayAccessSet, and defines the set method on that, and refactors array_set to support that instead of special casing individual array types.
1 parent 44a89e1 commit be6ad5e

File tree

14 files changed

+431
-118
lines changed

14 files changed

+431
-118
lines changed

src/main/java/com/laytonsmith/core/MainSandbox.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
public class MainSandbox {
77

88
public static void main(String[] args) throws Exception {
9-
9+
1010
}
1111
}

src/main/java/com/laytonsmith/core/MethodScriptCompiler.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2598,12 +2598,12 @@ private static void optimize(ParseTree tree, Environment env,
25982598

25992599
if(env.hasEnv(GlobalEnv.class)) {
26002600
// For testing, we frequently set this to null, so check this first.
2601-
env.getEnv(GlobalEnv.class).SetFlag("no-check-undefined", true);
2601+
env.getEnv(GlobalEnv.class).SetFlag(GlobalEnv.FLAG_NO_CHECK_UNDEFINED, true);
26022602
}
26032603
Procedure myProc = DataHandling.proc.getProcedure(tree.getTarget(), env, fakeScript, children.toArray(ParseTree[]::new));
26042604
tree.getNodeModifiers().merge(children.get(0).getNodeModifiers());
26052605
if(env.hasEnv(GlobalEnv.class)) {
2606-
env.getEnv(GlobalEnv.class).ClearFlag("no-check-undefined");
2606+
env.getEnv(GlobalEnv.class).ClearFlag(GlobalEnv.FLAG_NO_CHECK_UNDEFINED);
26072607
}
26082608
procs.peek().add(myProc); //Yep. So, we can move on with our lives now, and if it's used later, it could possibly be static.
26092609
} catch (ConfigRuntimeException e) {

src/main/java/com/laytonsmith/core/constructs/CArray.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import com.laytonsmith.core.functions.ArrayHandling;
1616
import com.laytonsmith.core.functions.BasicLogic;
1717
import com.laytonsmith.core.functions.DataHandling;
18+
import com.laytonsmith.core.natives.interfaces.ArrayAccessSet;
1819
import com.laytonsmith.core.natives.interfaces.Booleanish;
1920
import com.laytonsmith.core.natives.interfaces.Mixed;
2021
import com.laytonsmith.core.objects.ObjectModifier;
@@ -42,7 +43,7 @@
4243
*/
4344
@typeof("ms.lang.array")
4445
public class CArray extends Construct implements Iterable<Mixed>, Booleanish,
45-
com.laytonsmith.core.natives.interfaces.Iterable {
46+
com.laytonsmith.core.natives.interfaces.Iterable, ArrayAccessSet {
4647

4748
public static final CClassType TYPE = CClassType.get(CArray.class);
4849
private boolean associativeMode = false;
@@ -348,6 +349,7 @@ private void setAssociative() {
348349
* @param index
349350
* @param c
350351
*/
352+
@Override
351353
public void set(Mixed index, Mixed c, Target t) {
352354
if(!associativeMode) {
353355
if(index instanceof CNull) {
@@ -957,7 +959,8 @@ public CClassType[] getSuperclasses() {
957959

958960
@Override
959961
public CClassType[] getInterfaces() {
960-
return new CClassType[]{Booleanish.TYPE, com.laytonsmith.core.natives.interfaces.Iterable.TYPE};
962+
return new CClassType[]{Booleanish.TYPE, com.laytonsmith.core.natives.interfaces.Iterable.TYPE,
963+
ArrayAccessSet.TYPE};
961964
}
962965

963966
@Override

src/main/java/com/laytonsmith/core/constructs/CFixedArray.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.laytonsmith.core.exceptions.CRE.CREIndexOverflowException;
1010
import com.laytonsmith.core.exceptions.CRE.CREUnsupportedOperationException;
1111
import com.laytonsmith.core.exceptions.ConfigRuntimeException;
12+
import com.laytonsmith.core.natives.interfaces.ArrayAccessSet;
1213
import com.laytonsmith.core.natives.interfaces.Booleanish;
1314
import com.laytonsmith.core.natives.interfaces.Mixed;
1415

@@ -18,13 +19,14 @@
1819
import java.util.Set;
1920

2021
/**
21-
* This data type is meant to be used for low level systems programming. The API doesn't use it directly, though in
22-
* the interpreter implementation, it does use an actual fixed size array. For native code, however, this uses native
23-
* fixed size arrays, which assists with code mapping and is a required primitive for bootstrapping purposes.
22+
* This data type is meant to be used for low level systems programming. The API doesn't use it directly, though in the
23+
* interpreter implementation, it does use an actual fixed size array. For native code, however, this uses native fixed
24+
* size arrays, which assists with code mapping and is a required primitive for bootstrapping purposes.
2425
*/
2526
@typeof("ms.lang.fixed_array")
2627
public class CFixedArray extends Construct implements
27-
java.lang.Iterable<Mixed>, Booleanish, com.laytonsmith.core.natives.interfaces.Iterable {
28+
java.lang.Iterable<Mixed>, Booleanish, com.laytonsmith.core.natives.interfaces.Iterable,
29+
ArrayAccessSet {
2830

2931
public static final CClassType TYPE = CClassType.get(CFixedArray.class);
3032
private Mixed[] data;
@@ -78,6 +80,12 @@ private void validateSet(Mixed value, Target t) {
7880
}
7981
}
8082

83+
@Override
84+
public void set(Mixed index, Mixed value, Target t) {
85+
int in = ArgumentValidation.getInt32(index, t);
86+
set(in, value, t);
87+
}
88+
8189
public void set(int index, Mixed value, Target t) {
8290
validateSet(value, t);
8391
if(index >= data.length || index < 0) {
@@ -123,7 +131,8 @@ public Iterator<Mixed> iterator() {
123131

124132
@Override
125133
public CClassType[] getInterfaces() {
126-
return new CClassType[]{Booleanish.TYPE, com.laytonsmith.core.natives.interfaces.Iterable.TYPE};
134+
return new CClassType[]{Booleanish.TYPE, com.laytonsmith.core.natives.interfaces.Iterable.TYPE,
135+
ArrayAccessSet.TYPE};
127136
}
128137

129138
@Override

src/main/java/com/laytonsmith/core/constructs/CReal2dMatrix.java

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ public boolean isAssociative() {
155155
}
156156

157157
@Override
158-
public CArray get(Mixed index, Target t) throws ConfigRuntimeException {
158+
public CReal2dMatrixRow get(Mixed index, Target t) throws ConfigRuntimeException {
159159
return get(ArgumentValidation.getInt32(index, t), t);
160160
}
161161

@@ -165,16 +165,11 @@ public Mixed get(String index, Target t) throws ConfigRuntimeException {
165165
}
166166

167167
@Override
168-
public CArray get(int index, Target t) throws ConfigRuntimeException {
168+
public CReal2dMatrixRow get(int index, Target t) throws ConfigRuntimeException {
169169
if(index >= getRowCount() || index < 0) {
170170
throw new CRERangeException("Matrix range out of bounds.", t);
171171
}
172-
double[] d = getRow(index, t);
173-
CArray ret = new CArray(t);
174-
for(int i = 0; i < d.length; i++) {
175-
ret.push(new CDouble(d[i], t), t);
176-
}
177-
return ret;
172+
return new CReal2dMatrixRow(this, index);
178173
}
179174

180175
@Override
@@ -214,6 +209,13 @@ public long size() {
214209
return getRowCount();
215210
}
216211

212+
public CReal2dMatrix deepClone() {
213+
double[] cloneData = new double[this.data.length];
214+
System.arraycopy(this.data, 0, cloneData, 0, this.data.length);
215+
CReal2dMatrix clone = new CReal2dMatrix(this.rows, this.columns, cloneData);
216+
return clone;
217+
}
218+
217219
private int getPosition(int row, int column) {
218220
return row * columns + column;
219221
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package com.laytonsmith.core.constructs;
2+
3+
import com.laytonsmith.PureUtilities.Version;
4+
import com.laytonsmith.annotations.typeof;
5+
import com.laytonsmith.core.ArgumentValidation;
6+
import com.laytonsmith.core.MSVersion;
7+
import com.laytonsmith.core.exceptions.CRE.CRECastException;
8+
import com.laytonsmith.core.exceptions.ConfigRuntimeException;
9+
import com.laytonsmith.core.natives.interfaces.AbstractMixedClass;
10+
import com.laytonsmith.core.natives.interfaces.ArrayAccessSet;
11+
import com.laytonsmith.core.natives.interfaces.Mixed;
12+
import java.util.HashSet;
13+
import java.util.Set;
14+
15+
/**
16+
*
17+
* @author Cailin
18+
*/
19+
@typeof("ms.lang.Real2dMatrixRow")
20+
public class CReal2dMatrixRow extends AbstractMixedClass implements com.laytonsmith.core.natives.interfaces.Iterable,
21+
ArrayAccessSet {
22+
23+
@SuppressWarnings("FieldNameHidesFieldInSuperclass")
24+
public static final CClassType TYPE = CClassType.get(CReal2dMatrixRow.class);
25+
26+
CReal2dMatrix parent;
27+
int rowIndex;
28+
29+
public CReal2dMatrixRow(CReal2dMatrix parent, int rowIndex) {
30+
this.parent = parent;
31+
this.rowIndex = rowIndex;
32+
}
33+
34+
@Override
35+
public String docs() {
36+
return "This class is a reference to a row in a matrix. The underlying \"array\" is shallow, and changes to"
37+
+ " this data will be reflected in the parent matrix.";
38+
}
39+
40+
@Override
41+
public Version since() {
42+
return MSVersion.V3_3_5;
43+
}
44+
45+
@Override
46+
public CClassType[] getSuperclasses() {
47+
return new CClassType[]{Mixed.TYPE};
48+
}
49+
50+
@Override
51+
public CClassType[] getInterfaces() {
52+
return new CClassType[]{com.laytonsmith.core.natives.interfaces.Iterable.TYPE, ArrayAccessSet.TYPE};
53+
}
54+
55+
@Override
56+
public Mixed get(String index, Target t) throws ConfigRuntimeException {
57+
throw new CRECastException("Real2dMatrix only supports int keys.", t);
58+
}
59+
60+
@Override
61+
public CDouble get(int index, Target t) throws ConfigRuntimeException {
62+
return new CDouble(getNative(index, t), t);
63+
}
64+
65+
@Override
66+
public Mixed get(Mixed index, Target t) throws ConfigRuntimeException {
67+
return get(ArgumentValidation.getInt32(index, t), t);
68+
}
69+
70+
@Override
71+
public Set<Mixed> keySet() {
72+
Set<Mixed> set = new HashSet<>();
73+
for(int i = 0; i < parent.columns; i++) {
74+
set.add(new CInt(i, Target.UNKNOWN));
75+
}
76+
return set;
77+
}
78+
79+
@Override
80+
public boolean isAssociative() {
81+
return false;
82+
}
83+
84+
@Override
85+
public boolean canBeAssociative() {
86+
return false;
87+
}
88+
89+
@Override
90+
public Mixed slice(int begin, int end, Target t) {
91+
CArray ret = new CArray(t);
92+
int step = (begin <= end) ? 1 : -1;
93+
94+
// Note: loop includes 'begin', excludes 'end', just like typical slice semantics
95+
for(int i = begin; i != end; i += step) {
96+
CDouble d = get(i, t);
97+
ret.push(d, t);
98+
}
99+
100+
return ret;
101+
}
102+
103+
@Override
104+
public boolean getBooleanValue(Target t) {
105+
// 0 dimension matrices are not possible, so this will
106+
// always have at least one value in it, thus always
107+
// true.
108+
return true;
109+
}
110+
111+
@Override
112+
public long size() {
113+
return parent.columns;
114+
}
115+
116+
@Override
117+
public void set(Mixed index, Mixed value, Target t) {
118+
int in = ArgumentValidation.getInt32(index, t);
119+
double d = ArgumentValidation.getDouble(value, t);
120+
setNative(in, d, t);
121+
}
122+
123+
@Override
124+
public String toString() {
125+
return "[Real2dMatrixRow]";
126+
}
127+
128+
public void setNative(int index, double value, Target t) {
129+
parent.data[parent.columns * this.rowIndex + index] = value;
130+
}
131+
132+
public double getNative(int index, Target t) {
133+
return parent.data[parent.columns * this.rowIndex + index];
134+
}
135+
136+
}

src/main/java/com/laytonsmith/core/constructs/IVariableList.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ public IVariable get(String name, Target t, boolean bypassAssignedCheck, Environ
9191
// non-strict mode it will be a compiler warning.
9292
// ==, not .equals
9393
if(v.ival() == CNull.UNDEFINED && !bypassAssignedCheck
94-
&& env.getEnv(GlobalEnv.class).GetFlag("no-check-undefined") == null) {
94+
&& env.getEnv(GlobalEnv.class).GetFlag(GlobalEnv.FLAG_NO_CHECK_UNDEFINED) == null) {
9595
MSLog.GetLogger().Log(MSLog.Tags.RUNTIME, LogLevel.ERROR, "Using undefined variable: " + name, t);
9696
}
9797
v.setTarget(t);

0 commit comments

Comments
 (0)